﻿using FixPointUnity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Unity.Mathematics;

namespace FixPointUnityThin
{
    //搞一个克制版的定点数学库
    static class ThinFixMath
    {
        public const int Zero = 0;
        public const int Shift = 16;
        public const int One = 1 << Shift;


        public const int Pi = (int)(13493037705L >> 16); //(int)(Math.PI * 65536.0) << 16;
        public const int Pi2 = (int)(26986075409L >> 16);
        public const int PiHalf = (int)(6746518852L >> 16);
        public const int E = (int)(11674931555L >> 16);

        #region 四则运算 +-*/%

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static int Add(int a, int b)
        {
            return a + b;
        }


        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static int Sub(int a, int b)
        {
            return a - b;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static int Mul(int a, int b)
        {
            return (int)(((long)a * (long)b) >> Shift);
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]

        public static int Div(int a, int b)
        {
            if (b == int.MinValue || b == 0)
            {
                FixedUtil.InvalidArgument("Fixed32.Div", "b", b);
                return 0;
            }

            return (int)(((long)a << 16) / b);
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static int Mod(int a, int b)
        {
            if (b == 0)
            {
                FixedUtil.InvalidArgument("Fixed32.Mod", "b", b);
                return 0;
            }

            return a % b;
        }
        #endregion
        public static int Abs(int x)
        {
            // \note fails with MinValue
            int mask = x >> 31;
            return (x + mask) ^ mask;
        }


        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static int tofix(float v)
        {
            return (int)(v * 0x10000);
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static float tofloat(int v)
        {
            return ((float)v) / 0x10000;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static int2 tofix(float2 v)
        {
            return new int2(tofix(v.x), tofix(v.y));
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static float2 tofloat(int2 v)
        {
            return new float2(tofloat(v.x), tofloat(v.y));
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static int3 tofix(float3 v)
        {
            return new int3(tofix(v.x), tofix(v.y), tofix(v.z));
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static float3 tofloat(int3 v)
        {
            return new float3(tofloat(v.x), tofloat(v.y), tofloat(v.z));
        }
    }
}
